using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Mapster;
using Microsoft.EntityFrameworkCore;
using WebSMS.Core.ResponseEntity;

namespace WebSMS;

public class MenuService : ITerMenu,ITransient
{
    private readonly IRepository<MenuPo> _repo;
    private readonly IRepository<UserMenuAuthorityLinks> _userMenuLinks;
    private readonly IRepository<RuleMenuLinks> _ruleMenuLinks;
    public MenuService(IRepository<MenuPo> repository,IRepository<UserMenuAuthorityLinks> userMenuLinks,IRepository<RuleMenuLinks> ruleMenuLinks)
    {
        _repo = repository;
        _userMenuLinks = userMenuLinks;
        _ruleMenuLinks = ruleMenuLinks;
    }
    public async Task<bool> UpdateMenu(MenuPo menu)
    {
        await _repo.UpdateNowAsync(menu);
        return true;
    }

    public async Task<bool> DeleteMenu(Guid menuId)
    {
        //判断是否存在该菜单
        MenuPo menu = await _repo.FirstOrDefaultAsync(m => m.Id == menuId);
        //判断是否存在子菜单
        IQueryable<MenuPo> menuList = _repo.Where(m => m.ParentMenu == menu.Id);
        var ruleMenu = _ruleMenuLinks.Where(rm => rm.MenuId == menuId);
        var userMenu = _userMenuLinks.Where(um => um.MenuId == menuId);
       
        if (menuList.Any() || ruleMenu.Any() || userMenu.Any())
        {
            return false;
        }

        await _repo.DeleteNowAsync(menu);
        return true;
    }

    public async Task<bool> AddMenu(MenuPo menu)
    {
       await _repo.InsertNowAsync(menu);
        return true;
    }
    
    public IQueryable<MenuPo> GetMenuAll()
    {
        return  _repo.AsQueryable();
    }

    public async Task<List<MenuCollection>> GetMenuList(string userId,List<UserRuleLinks> rules)
    {
        List<MenuPo> menuList = await _repo.AsQueryable().ToListAsync();
        return await BuildMenuTreeAsync(menuList,userId,rules);
    }

    public async Task<List<MenuCollection>> BuildMenuTreeAsync(List<MenuPo> menuList, string userId, List<UserRuleLinks> rules)
    {
        // 根据 userId 获取用户的菜单权限
        var userGuid = Guid.Parse(userId);
        var userMenuIds = await _userMenuLinks
            .Where(um => um.UserId == userGuid)
            .Select(um => um.MenuId)
            .ToListAsync();

        // 根据 rules 获取规则的菜单权限
        var ruleIds = rules.Select(r => r.RuleId).ToList();
        var ruleMenuIds = await _ruleMenuLinks
            .Where(rm => ruleIds.Contains(rm.RuleId))
            .Select(rm => rm.MenuId)
            .ToListAsync();

        // 合并两个列表并去重
        var filteredMenuIds = userMenuIds.Concat(ruleMenuIds).Distinct().ToHashSet();

        // 构建菜单字典，并过滤掉不在 filteredMenuIds 中的菜单
        var menuDictionary = menuList
            .Where(m => m.Id.HasValue && !filteredMenuIds.Contains(m.Id.Value))
            .ToDictionary(m => m.Id.Value, m => new MenuCollection
            {
                Id = m.Id,
                Name = m.Name,
                Path = m.Path,
                Icon = m.Icon,
                ParentMenu = m.ParentMenu,
                Priority = m.Priority
            });

        // 构建菜单树
        foreach (var menu in menuDictionary.Values)
        {
            if (menu.ParentMenu.HasValue && menuDictionary.TryGetValue(menu.ParentMenu.Value, out var parent))
            {
                parent.Children.Add(menu);
            }
        }

        // 提取所有顶级菜单（即那些没有父菜单的菜单）并根据优先级排序
        var rootMenus = menuDictionary.Values
            .Where(m => !m.ParentMenu.HasValue)
            .OrderBy(m => m.Priority) // 根据 Priority 排序
            .ToList();

        return rootMenus;
    }

    /*public async Task<IQueryable> GetUserMenuById(Guid id)
    {
        from um in _userMenuLinks.Where(ua => ua.Id == id)
            join menu in _repo.AsQueryable() on menu.Id equals um.MenuId
            select new
            {
                MenuId = menu.Id,
                MenuName = menu.Name,
                MenuPath = menu.Path,
                MenuIcon = menu.Icon,
                MenuPriority = menu.Priority
            };
    }*/

}